﻿using System;
using System.Drawing;
using System.Threading.Tasks;
using OpenCvSharp;
using ScienceAppService.Entities;
using ScienceRpcServe.Protos;
using static System.Net.Mime.MediaTypeNames;
using Point = OpenCvSharp.Point;
using Size = OpenCvSharp.Size;

namespace ScienceAppService.Utils;
public class AppCvUtil
{
    public static Mat PaintTagMat(TagInfoResponse tags)
    {
        var mat = new Mat(1024, 1400, MatType.CV_8UC4, new Scalar(0, 0, 0, 0));

        var font = HersheyFonts.HersheySimplex;

        var fontScale = 0.6;

        var color = new Scalar(250, 250, 250, 250);

        var thickness = 1;

        // 左上角
        for (var i = 0; i < tags.PatientInfo.Count; i++)
        {
            if (!string.IsNullOrEmpty(tags.PatientInfo[i]))
                Cv2.PutText(mat, tags.PatientInfo[i], new Point(10, 25 + i * 22), font, fontScale, color, thickness);
        }

        // 左下角
        for (var i = 0; i < tags.ImageInfo.Count; i++)
        {
            if (!string.IsNullOrEmpty(tags.ImageInfo[i]))
                Cv2.PutText(mat, tags.ImageInfo[i], new Point(10, 1000 - i*22), font, fontScale, color, thickness);
        }

        // 右上角
        for (var i = 0; i < tags.StudyInfo.Count; i++)
        {
            if (!string.IsNullOrEmpty(tags.StudyInfo[i]))
                Cv2.PutText(mat, tags.StudyInfo[i], new Point(1330 - tags.StudyInfo[i].Length * 12, 25 + i * 22), font, fontScale, color, thickness);
        }

        return mat;
    }

    public static Mat? PaintMaskByVal(Mat? mask)
    {
        if (mask == null) return null;
        var mat = new Mat(mask.Rows, mask.Cols, MatType.CV_8UC4, new Scalar(0, 0, 0, 0));
        for (var i = 0; i < mask.Rows; i++)
        {
            for (var j = 0; j < mask.Cols; j++)
            {
                var val = mask.At<byte>(i, j);
                switch (val)
                {
                    case <= 0:
                        continue;
                    case 1:
                        mat.Set<Vec4b>(i, j, new Vec4b(SegMarkColor.UlanColor.B, 
                            SegMarkColor.UlanColor.G, SegMarkColor.UlanColor.R, 100));
                        break;
                    case 2:
                        mat.Set<Vec4b>(i, j, new Vec4b(SegMarkColor.RadiusColor.B, 
                            SegMarkColor.RadiusColor.G, SegMarkColor.RadiusColor.R, 100));
                        break;
                    case 3:
                        mat.Set<Vec4b>(i, j, new Vec4b(SegMarkColor.TfccColor.B, 
                            SegMarkColor.TfccColor.G, SegMarkColor.TfccColor.R, 100));
                        break;
                }
            }
        }

        return mat;
    }

    public static Mat? ResizeLabelMat(Mat? mask, double height)
    {
        if (mask == null) return null;

        var dst = new Mat(new Size(mask.Width, (int)mask.Height * AppServiceEnv.ImageInfo.ImageFactor), MatType.CV_8UC4);
        Cv2.Resize(mask, dst, new Size(mask.Width, (int)height)
            , 0, 0, InterpolationFlags.Nearest);

        return dst;
    }

    /// <summary>
    /// 擦除方法
    /// </summary>
    /// <param name="p"></param>
    /// <param name="drawMat"></param>
    /// <param name="color"></param>
    /// <param name="borderBrush"></param>
    /// <returns></returns>
    public static Mat? CleanMat(int[] p, Mat? mat, Color color, int borderBrush = 5)
    {
        if (mat == null) return null;

        var newMat = new Mat(mat.Rows, mat.Cols, MatType.CV_8UC1, new Scalar(0));
        newMat.Circle(p[0], p[1], borderBrush, new Scalar(200), -1);

        var drawMat = mat.Clone();

        for (var i = 0; i < drawMat.Height; i++)
        {
            for (var j = 0; j < drawMat.Width; j++)
            {
                var val = newMat.At<byte>(i, j);
                if (val > 0)
                {
                    drawMat.Set(i, j, new Vec4b(0, 0, 0, 0));
                }
            }
        }
        return drawMat;
    }

    /// <summary>
    /// 绘制方法
    /// </summary>
    /// <param name="p"></param>
    /// <param name="mat"></param>
    /// <param name="color"></param>
    /// <param name="borderBrush"></param>
    /// <returns></returns>
    public static Mat? DrawMat(int[] p, Mat? mat, Color color, int borderBrush = 5)
    {
        if(mat == null) return null;

        var drawMat = mat.Clone();

        var newMat = new Mat(drawMat.Rows, drawMat.Cols, MatType.CV_8UC4, new Scalar(0, 0, 0, 0));
        newMat.Circle(p[0], p[1], borderBrush, new Scalar(color.B, color.G, color.R, 100), -1);

        var greyMat = new Mat();
        var greyMatNew = new Mat();

        Cv2.CvtColor(drawMat, greyMat, ColorConversionCodes.BGR2GRAY);
        Cv2.CvtColor(newMat, greyMatNew, ColorConversionCodes.BGR2GRAY);

        var binaryMat = new Mat();
        var binaryMatNew = new Mat();

        Cv2.Threshold(greyMat, binaryMat, 10, 250, ThresholdTypes.Binary);
        Cv2.Threshold(greyMatNew, binaryMatNew, 10, 250, ThresholdTypes.Binary);

        var diffMat = new Mat();

        // 相当于如此
        //Cv2.Absdiff(binaryMatNew, binaryMat, diffMat);
        //diffMat = diffMat - binaryMat;
        Cv2.Subtract(binaryMatNew, binaryMat, diffMat);

        for (var i = 0; i < diffMat.Height; i++)
        {
            for (var j = 0; j < diffMat.Width; j++)
            {
                var val = diffMat.At<byte>(i, j);
                if (val > 0)
                {
                    drawMat.Set(i, j, new Vec4b(color.B, color.G, color.R, 100));
                }
            }
        }
        return drawMat;
    }

    public static Mat? CreateLableMat(Mat? mat)
    {
        return mat == null ? null : new Mat(mat.Rows, mat.Cols, MatType.CV_8UC4, new Scalar(0, 0, 0, 0));
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="borderness"></param>
    /// <param name="color"></param>
    /// <returns></returns>
    public static Mat? CreateBorderThicknessMat(int borderness, Color color)
    {
        var mat = new Mat(30, 30, MatType.CV_8UC4, new Scalar(0, 0, 0, 0));
        mat.Line(0,15,30,15, new Scalar(color.B, color.G, color.R, 100),borderness);
        return mat;
    }

}
